{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Image Classification"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In this example,I created a Neural Network to do image classification. The dataset is from Kaggle: https://www.kaggle.com/cactus3/basicshapes This is a dataset containing 100 pictures each of circle rectangle and triangle."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. load packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 111,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "import matplotlib.cm as cm\n",
    "\n",
    "import tensorflow as tf #my tensorflow version is 1.4"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. load data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#load data\n",
    "import scipy \n",
    "imgs=np.ndarray(shape=(300,28,28,3)) #300 images, each image is 28*28, 3 channels: RGB \n",
    "classnames=['circles','squares','triangles']\n",
    "for c in range(0,3):\n",
    "    for n in range(1,101):\n",
    "        filenames='drawing('+str(n)+').png'\n",
    "        img = scipy.misc.imread(classnames[c]+'\\\\'+filenames)\n",
    "        imgs[n-1+c*100,:]=img\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "images = np.multiply(imgs, 1.0 / 255.0) # Normalization (make pixel value 0-1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x21e5ddf9828>"
      ]
     },
     "execution_count": 69,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21e5dd98ac8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure()\n",
    "fig.add_subplot(1,3,1)\n",
    "plt.imshow(images[1,:])\n",
    "fig.add_subplot(1,3,2)\n",
    "plt.imshow(images[101,:])\n",
    "fig.add_subplot(1,3,3)\n",
    "plt.imshow(images[201,:])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Create labels"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# one hot encoding of the lable \n",
    "#circle => 1,0,0\n",
    "#square => 0,1,0\n",
    "#triangle=> 0,0,1\n",
    "labels=np.ndarray(shape=(300,3))\n",
    "for n in range(0,100):\n",
    "    labels[n,:]=np.array([1,0,0])\n",
    "for n in range(100,200):\n",
    "    labels[n,:]=np.array([0,1,0])\n",
    "for n in range(200,300):\n",
    "    labels[n,:]=np.array([0,0,1])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. Prepare data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    " # shuffle the (image+lable)\n",
    "perm = np.arange(300)\n",
    "np.random.shuffle(perm)\n",
    "shuffled_images = images[perm,:]\n",
    "shuffled_labels = labels[perm,:]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.image.AxesImage at 0x21e5d40a898>"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n2nwAG5VSFSIyP9GeF3z3Uo/7BJ958EJQ3GVfK1as0PE999xj5ZKYiliOFKur+aRgOj012FXDhg3T\ncVVVVZB/9XLEWNsjR45YbfMAbvPQbF9dd911Or7tttusnPnvN4ynvNt9h66U+juA/zgvTwbwciJ+\nGcCfAu4XhYx19Rdr2311dQ49Vyn1/xXz3wPIbe0LRaRcRKpFpNo91otSDuvqrw7VlnVNb0nfFFUt\nhz+qNvIvKaVKlFIlAwcOTPZyFBHW1V9t1ZZ1TW9dnYCtF5E8pVSdiOQBaGj3T3hi2rRpVvvOO++0\n2uYJNdOnT7dy5lI8d47YfAz+nXfesXK//fabji+//PLOdbhzIq2rexC0uRuhm/NR3759ddzU1BT2\n5SKrrXsPyDyM2/xv9tVZZ52lY3f56aZNm3TsntAUhK6+Q68CUJaIywCsbeNrKX2wrv5ibbuBjixb\nXAXgYwDDRKRWRKYBqABwlYjsAnBlok1phHX1F2vbfbU75aKUKm0lNaGV171mfpwCgDfffNNqv/DC\nCzqeMmWKlcvOztbxyJEjrZw5reLejFq0aJGO+/ULZvlwKtTVXXJpbv7vHuThI3PaLcgpprhr6+5A\nak4nZmRkRNGFWJl1LSgosHLmU7Nh4JOiRESe4IBOROQJDuhERJ5I/y3sYtazZ0+rff/99+vYPU1o\nz549Ot6/f3+rf+c555xjtd15e1+486lnnnmmjvft22flzMfH3e95uvJ1q4PMzMxWc+5OjDk5OWF3\nJ1buvZGwl+PyHToRkSc4oBMReYJTLiFyP3qau+uZMbUwp5aqq6utnPn0oS9TLr5ydyQ1dxWsr6+3\ncr5PuZhPP0eB79CJiDzBAZ2IyBMc0ImIPME5dEoZ5rLFgwcPWjlzawRfmEszc3Nb3Xo+7bjz4vn5\n+To2l+4CQFFRUSR9issXX3xhtSdOnBjq9fgOnYjIExzQiYg8wQGdiMgTnEOnlDFkyBAdu49If/PN\nNzpO1/lm9ySfDRs26NjdajmdZWVlWW3zKDvzRC8AuOKKK3Tsy9a6zc3NOq6trbVyY8eODfXafIdO\nROQJDuhERJ7glAulDPOkmzFjxlg5c3pi3LhxkfUpWUeOHNHxmjVrrFyfPn10fO6550bWp7C5JxaN\nHj1ax5WVlVbOPJ1r0KBB4XYsJOaJTADw2muv6Xjy5MlWzv3eBI3v0ImIPMEBnYjIExzQiYg8wTl0\n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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21e5dd9a0f0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "#check the image are shuffled\n",
    "fig = plt.figure()\n",
    "fig.add_subplot(1,3,1)\n",
    "plt.imshow(shuffled_images[1,:])\n",
    "fig.add_subplot(1,3,2)\n",
    "plt.imshow(shuffled_images[101,:])\n",
    "fig.add_subplot(1,3,3)\n",
    "plt.imshow(shuffled_images[201,:])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 1.  0.  0.]\n",
      "[ 1.  0.  0.]\n",
      "[ 1.  0.  0.]\n"
     ]
    }
   ],
   "source": [
    "#confirm after shuffule, the label are correct\n",
    "print(shuffled_labels[1,:])\n",
    "print(shuffled_labels[101,:])\n",
    "print(shuffled_labels[201,:])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "VALIDATION_SIZE = 50\n",
    "\n",
    "validation_images = shuffled_images[:VALIDATION_SIZE]\n",
    "validation_labels = shuffled_labels[:VALIDATION_SIZE]\n",
    "\n",
    "train_images = shuffled_images[VALIDATION_SIZE:]\n",
    "train_labels = shuffled_labels[VALIDATION_SIZE:]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. Generate Model (CNN)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# weight initialization\n",
    "def weight_variable(shape):\n",
    "    initial = tf.truncated_normal(shape, stddev=0.1)\n",
    "    return tf.Variable(initial)\n",
    "\n",
    "def bias_variable(shape):\n",
    "    initial = tf.constant(0.1, shape=shape)\n",
    "    return tf.Variable(initial)\n",
    "\n",
    "def conv2d(x, W):\n",
    "    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME') \n",
    "\n",
    "def max_pool_2x2(x):\n",
    "    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# input & output of NN\n",
    "\n",
    "image_width=28\n",
    "image_height=28 # each image is 28*28\n",
    "labels_count=3 # 3 shapes:circle, square, triangle\n",
    "\n",
    "# images\n",
    "x = tf.placeholder('float32', shape=[None, image_width , image_height,3],name='x')\n",
    "# labels\n",
    "y_ = tf.placeholder('float32', shape=[None, labels_count])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(?, 14, 14, 32)\n"
     ]
    }
   ],
   "source": [
    "# first convolutional layer\n",
    "W_conv1 = weight_variable([5, 5, 3, 32]) #32 convolution kernels. each kernel is 5*5*3 (3 means 3 channels:RGB)\n",
    "b_conv1 = bias_variable([32])\n",
    "\n",
    "# (?,784) => (?,28,28,3)\n",
    "\n",
    "image = tf.reshape(x, [-1,image_width , image_height,3]) # -1 means auto calculate the size: 50 or 250. 3 means RGB\n",
    "#print (image.get_shape()) \n",
    "\n",
    "\n",
    "h_conv1 = tf.nn.relu(conv2d(image, W_conv1) + b_conv1)\n",
    "#print (h_conv1.get_shape()) \n",
    "h_pool1 = max_pool_2x2(h_conv1)\n",
    "print (h_pool1.get_shape())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(?, 7, 7, 64)\n"
     ]
    }
   ],
   "source": [
    "# second convolutional layer\n",
    "W_conv2 = weight_variable([5, 5, 32, 64])# 64 kernel, each kernel 5*5*32. (after first convolution, we have 32 channels)\n",
    "b_conv2 = bias_variable([64])\n",
    "\n",
    "h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)\n",
    "\n",
    "h_pool2 = max_pool_2x2(h_conv2)\n",
    "print (h_pool2.get_shape()) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# densely connected layer\n",
    "W_fc1 = weight_variable([7 * 7 * 64, 1024])\n",
    "b_fc1 = bias_variable([1024])\n",
    "\n",
    "# (?, 7, 7, 64) => (?, 3136)\n",
    "h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])\n",
    "\n",
    "h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)\n",
    "#print (h_fc1.get_shape()) # => (?, 1024)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# dropout\n",
    "keep_prob = tf.placeholder('float')\n",
    "h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# readout layer for deep net\n",
    "W_fc2 = weight_variable([1024, labels_count])\n",
    "b_fc2 = bias_variable([labels_count])\n",
    "\n",
    "y = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "LEARNING_RATE = 1e-4\n",
    "# cost function\n",
    "cross_entropy = -tf.reduce_sum(y_*tf.log(y))\n",
    "\n",
    "\n",
    "# optimisation function\n",
    "train_step = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(cross_entropy)\n",
    "\n",
    "# evaluation\n",
    "correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1)) # predicted label y compare to real label y\n",
    "\n",
    "accuracy = tf.reduce_mean(tf.cast(correct_prediction, 'float'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# prediction function\n",
    "#[0.1, 0.9, 0.2] => square\n",
    "predict = tf.argmax(y,1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "epochs_completed = 0\n",
    "index_in_epoch = 0\n",
    "num_examples = train_images.shape[0]\n",
    "\n",
    "# serve data by batches\n",
    "def next_batch(batch_size):\n",
    "    \n",
    "    global train_images\n",
    "    global train_labels\n",
    "    global index_in_epoch\n",
    "    global epochs_completed\n",
    "    \n",
    "    start = index_in_epoch\n",
    "    index_in_epoch += batch_size\n",
    "    \n",
    "    # when all trainig data have been already used, it is reorder randomly    \n",
    "    if index_in_epoch > num_examples:\n",
    "        # finished epoch\n",
    "        epochs_completed += 1\n",
    "        # shuffle the data\n",
    "        perm = np.arange(num_examples)\n",
    "        np.random.shuffle(perm)\n",
    "        train_images = train_images[perm]\n",
    "        train_labels = train_labels[perm]\n",
    "        # start next epoch\n",
    "        start = 0\n",
    "        index_in_epoch = batch_size\n",
    "        assert batch_size <= num_examples\n",
    "    end = index_in_epoch\n",
    "    return train_images[start:end], train_labels[start:end]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. Train Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# start TensorFlow session\n",
    "init = tf.initialize_all_variables()\n",
    "sess = tf.InteractiveSession()\n",
    "\n",
    "sess.run(init)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "training_accuracy / validation_accuracy => 0.34 / 0.42 for step 0\n",
      "training_accuracy / validation_accuracy => 0.20 / 0.26 for step 10\n",
      "training_accuracy / validation_accuracy => 0.44 / 0.44 for step 20\n",
      "training_accuracy / validation_accuracy => 0.48 / 0.42 for step 30\n",
      "training_accuracy / validation_accuracy => 0.38 / 0.28 for step 40\n",
      "training_accuracy / validation_accuracy => 0.48 / 0.46 for step 50\n",
      "training_accuracy / validation_accuracy => 0.62 / 0.40 for step 60\n",
      "training_accuracy / validation_accuracy => 0.36 / 0.38 for step 70\n",
      "training_accuracy / validation_accuracy => 0.54 / 0.56 for step 80\n",
      "training_accuracy / validation_accuracy => 0.70 / 0.50 for step 90\n",
      "training_accuracy / validation_accuracy => 0.54 / 0.38 for step 100\n",
      "training_accuracy / validation_accuracy => 0.58 / 0.58 for step 110\n",
      "training_accuracy / validation_accuracy => 0.62 / 0.64 for step 120\n",
      "training_accuracy / validation_accuracy => 0.70 / 0.74 for step 130\n",
      "training_accuracy / validation_accuracy => 0.80 / 0.70 for step 140\n",
      "training_accuracy / validation_accuracy => 0.70 / 0.58 for step 150\n",
      "training_accuracy / validation_accuracy => 0.82 / 0.66 for step 160\n",
      "training_accuracy / validation_accuracy => 0.82 / 0.76 for step 170\n",
      "training_accuracy / validation_accuracy => 0.68 / 0.66 for step 180\n",
      "training_accuracy / validation_accuracy => 0.82 / 0.66 for step 190\n",
      "training_accuracy / validation_accuracy => 0.72 / 0.70 for step 200\n",
      "training_accuracy / validation_accuracy => 0.78 / 0.66 for step 210\n",
      "training_accuracy / validation_accuracy => 0.70 / 0.68 for step 220\n",
      "training_accuracy / validation_accuracy => 0.74 / 0.66 for step 230\n",
      "training_accuracy / validation_accuracy => 0.86 / 0.74 for step 240\n",
      "training_accuracy / validation_accuracy => 0.82 / 0.68 for step 250\n",
      "training_accuracy / validation_accuracy => 0.70 / 0.70 for step 260\n",
      "training_accuracy / validation_accuracy => 0.82 / 0.74 for step 270\n",
      "training_accuracy / validation_accuracy => 0.92 / 0.76 for step 280\n",
      "training_accuracy / validation_accuracy => 0.88 / 0.66 for step 290\n",
      "training_accuracy / validation_accuracy => 0.84 / 0.76 for step 300\n",
      "training_accuracy / validation_accuracy => 0.92 / 0.74 for step 310\n",
      "training_accuracy / validation_accuracy => 0.86 / 0.72 for step 320\n",
      "training_accuracy / validation_accuracy => 0.78 / 0.72 for step 330\n",
      "training_accuracy / validation_accuracy => 0.84 / 0.70 for step 340\n",
      "training_accuracy / validation_accuracy => 0.78 / 0.70 for step 350\n",
      "training_accuracy / validation_accuracy => 0.88 / 0.70 for step 360\n",
      "training_accuracy / validation_accuracy => 0.82 / 0.74 for step 370\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.78 for step 380\n",
      "training_accuracy / validation_accuracy => 0.88 / 0.76 for step 390\n",
      "training_accuracy / validation_accuracy => 0.94 / 0.80 for step 400\n",
      "training_accuracy / validation_accuracy => 0.88 / 0.74 for step 410\n",
      "training_accuracy / validation_accuracy => 0.92 / 0.74 for step 420\n",
      "training_accuracy / validation_accuracy => 0.88 / 0.78 for step 430\n",
      "training_accuracy / validation_accuracy => 0.82 / 0.74 for step 440\n",
      "training_accuracy / validation_accuracy => 0.90 / 0.78 for step 450\n",
      "training_accuracy / validation_accuracy => 0.86 / 0.76 for step 460\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.80 for step 470\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.80 for step 480\n",
      "training_accuracy / validation_accuracy => 0.94 / 0.78 for step 490\n",
      "training_accuracy / validation_accuracy => 0.92 / 0.82 for step 500\n",
      "training_accuracy / validation_accuracy => 0.94 / 0.84 for step 510\n",
      "training_accuracy / validation_accuracy => 0.94 / 0.82 for step 520\n",
      "training_accuracy / validation_accuracy => 0.94 / 0.82 for step 530\n",
      "training_accuracy / validation_accuracy => 0.92 / 0.80 for step 540\n",
      "training_accuracy / validation_accuracy => 0.94 / 0.80 for step 550\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.78 for step 560\n",
      "training_accuracy / validation_accuracy => 0.94 / 0.80 for step 570\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.78 for step 580\n",
      "training_accuracy / validation_accuracy => 0.90 / 0.80 for step 590\n",
      "training_accuracy / validation_accuracy => 0.90 / 0.82 for step 600\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.84 for step 610\n",
      "training_accuracy / validation_accuracy => 0.94 / 0.78 for step 620\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.80 for step 630\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.80 for step 640\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.84 for step 650\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.84 for step 660\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.80 for step 670\n",
      "training_accuracy / validation_accuracy => 0.94 / 0.82 for step 680\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.80 for step 690\n",
      "training_accuracy / validation_accuracy => 0.90 / 0.84 for step 700\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.84 for step 710\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.82 for step 720\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.84 for step 730\n",
      "training_accuracy / validation_accuracy => 0.94 / 0.84 for step 740\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.86 for step 750\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.86 for step 760\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.84 for step 770\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.82 for step 780\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.84 for step 790\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.84 for step 800\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.86 for step 810\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 820\n",
      "training_accuracy / validation_accuracy => 0.92 / 0.86 for step 830\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.86 for step 840\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.84 for step 850\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.86 for step 860\n",
      "training_accuracy / validation_accuracy => 0.92 / 0.84 for step 870\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.84 for step 880\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.88 for step 890\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 900\n",
      "training_accuracy / validation_accuracy => 0.94 / 0.86 for step 910\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.86 for step 920\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.84 for step 930\n",
      "training_accuracy / validation_accuracy => 0.94 / 0.86 for step 940\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.86 for step 950\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 960\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 970\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.86 for step 980\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.86 for step 990\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1000\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.84 for step 1010\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1020\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.88 for step 1030\n",
      "training_accuracy / validation_accuracy => 0.88 / 0.78 for step 1040\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1050\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1060\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.88 for step 1070\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1080\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.86 for step 1090\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.88 for step 1100\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.88 for step 1110\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1120\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.86 for step 1130\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1140\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1150\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.88 for step 1160\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.84 for step 1170\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.88 for step 1180\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.88 for step 1190\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1200\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1210\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1220\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1230\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.86 for step 1240\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1250\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.88 for step 1260\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.88 for step 1270\n",
      "training_accuracy / validation_accuracy => 0.96 / 0.88 for step 1280\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.88 for step 1290\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.86 for step 1300\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.86 for step 1310\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.88 for step 1320\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.86 for step 1330\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.88 for step 1340\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1350\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.88 for step 1360\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.88 for step 1370\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1380\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1390\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1400\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1410\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1420\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1430\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.88 for step 1440\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.88 for step 1450\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1460\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1470\n",
      "training_accuracy / validation_accuracy => 1.00 / 0.86 for step 1480\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.86 for step 1490\n",
      "training_accuracy / validation_accuracy => 0.98 / 0.88 for step 1499\n"
     ]
    }
   ],
   "source": [
    "TRAINING_ITERATIONS = 1500  # may change it to have more iterations if we use a complex dataset.\n",
    "\n",
    "DROPOUT = 0.5\n",
    "\n",
    "BATCH_SIZE = 50\n",
    "\n",
    "# visualisation variables\n",
    "train_accuracies = []\n",
    "validation_accuracies = []\n",
    "x_range = []\n",
    "\n",
    "display_step=10\n",
    "\n",
    "for i in range(TRAINING_ITERATIONS):\n",
    "\n",
    "    #get new batch\n",
    "    batch_xs, batch_ys = next_batch(BATCH_SIZE)        \n",
    "    \n",
    "    # check progress on every 1st,2nd,...,10th,20th,...,100th... step\n",
    "    if i%display_step == 0 or (i+1) == TRAINING_ITERATIONS:\n",
    "        \n",
    "        train_accuracy = accuracy.eval(feed_dict={x:batch_xs, \n",
    "                                                  y_: batch_ys, \n",
    "                                                  keep_prob: 1.0})\n",
    "        \n",
    "        if(VALIDATION_SIZE):\n",
    "            validation_accuracy = accuracy.eval(feed_dict={ x: validation_images[0:BATCH_SIZE], \n",
    "                                                            y_: validation_labels[0:BATCH_SIZE], \n",
    "                                                            keep_prob: 1.0})                                  \n",
    "            print('training_accuracy / validation_accuracy => %.2f / %.2f for step %d'%(train_accuracy, validation_accuracy, i))\n",
    "            \n",
    "            validation_accuracies.append(validation_accuracy)\n",
    "            \n",
    "        else:\n",
    "             print('training_accuracy => %.4f for step %d'%(train_accuracy, i))\n",
    "        train_accuracies.append(train_accuracy)\n",
    "        x_range.append(i)\n",
    "        \n",
    "        # increase display_step\n",
    "        #if i%(display_step*10) == 0 and i:\n",
    "        #    display_step *= 10\n",
    "    # train on batch\n",
    "    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys, keep_prob: DROPOUT})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 7.Evaluate Model "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 87,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "validation_accuracy => 0.8800\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n3FgjZG3UCQAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x21e5d64df28>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# check final accuracy on validation set  \n",
    "validation_accuracy = accuracy.eval(feed_dict={x: validation_images, \n",
    "                                                   y_: validation_labels, \n",
    "                                                   keep_prob: 1.0})\n",
    "print('validation_accuracy => %.4f'%validation_accuracy)\n",
    "plt.plot(x_range, train_accuracies,'-b', label='Training')\n",
    "plt.plot(x_range, validation_accuracies,'-g', label='Validation')\n",
    "plt.legend(loc='lower right', frameon=False)\n",
    "plt.ylim(ymax = 1.1, ymin = 0.7)\n",
    "plt.ylabel('accuracy')\n",
    "plt.xlabel('step')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The final accuracy in train set is almost 100%. The accuracy in validation set is 88%. We can improve it by adding more iterations in training. Or use a more complicated CNN. \n",
    "I also predict the label for one sample image. (a square)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 107,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "squares\\drawing(1).png\n",
      "(1, 28, 28, 3)\n"
     ]
    }
   ],
   "source": [
    "#Test with one image\n",
    "filenames = 'drawing(1).png'\n",
    "classnames='squares'\n",
    "print(classnames+'\\\\'+filenames)\n",
    "\n",
    "\n",
    "\n",
    "img = scipy.misc.imread(classnames+'\\\\'+filenames)\n",
    "\n",
    "\n",
    "img_input=np.ndarray(shape=(1,28,28,3))\n",
    "img_input[0,:]=np.multiply(img, 1.0 / 255.0).astype(float)\n",
    "print (img_input.shape) \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 113,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "my_prediction=y.eval(feed_dict={x: img_input,keep_prob: 1.0})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 0.00327732  0.99245739  0.00426531]]\n"
     ]
    }
   ],
   "source": [
    " print(my_prediction) # print the possibility of each shapes (circle, square,triangle)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "This image is a square\n"
     ]
    }
   ],
   "source": [
    "classname_index = np.argmax(my_prediction) \n",
    "allclass=['circle','square','triangle']\n",
    "predicted_classname=allclass[classname_index]\n",
    "print(\"This image is a \"+predicted_classname)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [default]",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
